import os
import re
# import json

import openpyxl
# from openpyxl.utils import get_column_letter, column_index_from_string


class Xls2lua:
    def __init__(self, file_path):
        self.__path = file_path
        self.__wb = openpyxl.load_workbook(self.__path, data_only=True)
        self.__ws = self.__wb.active
        # print("init...")

    def __get_rows(self):
        """
        根据xls工作表A2单元格的内容获取范围
        :return: min_row[int], max_row[int]
        """
        row_index = str(self.__ws.cell(2,1).value or "").split("-")
        min_row = int(row_index[0] or 5)
        max_row = int(row_index[1]) if len(row_index) == 2 and row_index[1] else self.__ws.max_row
        return min_row, max_row

    def __str2num(self, data):
        if data.endswith("W") or data.endswith("w"):
            res = float(data.rstrip("W").rstrip("w")) * 10000
        else:
            res = float(data)
        
        if res == int(res):
            return int(res)

        return res

    def __num2str(self, data):
        if data // 10000 > 0:
            res = data / 10000
            return f'{int(res)}W' if res == int(res) else f'{res}W'

        res = int(data) if data == int(data) else data
        return str(res)

    def __get_col_id(self, col_name):
        row = list(self.__ws.values)[2]
        desc_col_id = row.index(col_name)
        return desc_col_id

    def __write_xls(self, lst):
        nwb = openpyxl.Workbook()
        nws = nwb.active
        for v in lst:
            nws.append(v)

        dir_name = os.path.dirname(self.__path)
        path = f'{dir_name}/temp.xlsx'
        nwb.save(path)
        os.system(path)

    def __write_file(self, code, path=None):
        isOpen = path == None
        if not path:
            path = f'{os.path.dirname(self.__path)}/temp.lua'

        with open(path, 'w', encoding='utf-8') as obj:
            obj.write(code)

        if isOpen:
            os.system(path)

    def fmt_desc(self):
        """
        将描述格式化输出为描述&data
        """
        desc_col_id = self.__get_col_id("desc")
        lst = [c.value for c in list(self.__ws.columns)[desc_col_id]][4:]

        l = []
        for desc in lst:
            tmp = [desc]
            # print(desc)
            i = 0
            while True:
                pattern = "(\-?\d+(\.\d+)?[Ww]?)"
                match = re.search(pattern, tmp[0])
                if not match:
                    break
                i += 1
                tmp[0] = tmp[0].replace(match.group(1), f'<{chr(i+64)}>', 1)
                tmp.append(self.__str2num(match.group(1)))
                print(tmp[0])
            l.append(tmp)

        self.__write_xls(l)
        
    def generate_desc(self):
        """
        生成游戏内的描述
        """
        desc_col_id = self.__get_col_id("fmt_desc")
        lst = [c.value for c in list(self.__ws.columns)[desc_col_id]][4:]

        l = []
        for i, desc in enumerate(lst):
            tmp = []
            tmp.append(desc)
            # print(desc)
            while True:
                pattern = "<([A-K])>"
                match = re.search(pattern, tmp[0])
                if not match:
                    break
                row = i + 5
                col = ord(match.group(1)) - 64 + (desc_col_id + 1)
                data = str(self.__ws.cell(row, col).value)
                tmp[0] = tmp[0].replace(match.group(0), data, 1)
                
            l.append(tmp)

        self.__write_xls(l)

    def write_lua_cfg(self):
        code = f'gtable["{self.__ws.title}"] = {{'
        types = list(self.__ws.values)[1]
        keys = list(self.__ws.values)[2]
        rows = list(self.__ws.values)[4:]
        for row in rows:
            key = None
            j = 0
            for i, v in enumerate(row):
                if (not types[i]) or (v is None):
                    continue
                
                if not key:
                    key = v
                    if types[i] == 'i':
                        code += f'\n\n\t[{key}] = {{'
                    else:
                        code += f'\n\n\t["{key}"] = {{'

                if types[i] == 's1':
                    code += f'\n\t\t{keys[i]} = "{v}",'
                    continue
                    
                if types[i] == 's2':
                    code += f'\n\t\t{keys[i]} = [[{v}]],'
                    continue

                if types[i] == 'i':
                    code += f'\n\t\t{keys[i]} = {v},'
                    continue

                if types[i] == 'arr':
                    v = '", "'.join(v.split(', '))
                    code += f'\n\t\t{keys[i]} = {{"{v}"}},'
                    continue

                if types[i] == 'd':
                    j += 1
                    prefix, suffix = '', ', '
                    if (j - 1) % 5 == 0:
                        prefix = '\n\t\t'

                    tmp = int(v) if v == int(v) else v
                    code += f'{prefix}{keys[i]} = {tmp}{suffix}'
                    continue

                # 注释
                if types[i] == 'annotation':
                    for tmp in v.split('\n'):
                        code += f'\n\t\t-- {tmp}'                    

            code += '\n\t},'
        code += f'\n}}\n'
        # print(code)
        self.__write_file(code)

    def write_item_template(self, module):
        col_id = self.__get_col_id("name")
        lst = [c.value for c in list(self.__ws.columns)[col_id]][4:]

        require = 'local lst = require "game.config.先天气运.FateLst"\n'

        code = "local name = 'itemName'\n"
        code += "---@class cst.item\n"
        code += "---@field itemName Item\n"
        code += require
        code += "\n"
        code += "local cfg = lst[name]\n"
        code += "local pack = {\n"
        code += "\tname = string.formt('[%s]%s', cfg.rank, name),\n"
        code += "\n"
        code += "\t-- 显示相关\n"
        code += "\ttips = cfg.desc,\n"
        code += '\ticon = string.format("ReplaceableTextures\\\\CommandButtons\\\\BTNBS%d.blp", cfg.id),\n'
        code += '\tmodel = cfg.model or [[Objects\\InventoryItems\\tomeBrown\\tomeBrown.mdl]],\n'
        code += '\t-- size = 0,\n'
        code += '\n'
        code += '\tprice = 0,\n'
        code += '\n'
        code += '\t-- buffs = {},\n'
        code += '\tskill = cst.skill["使用物品（通用）"],\n'
        code += '\n'
        code += '\t-- stackable = true,\n'
        code += '\t-- maxStack = 8,\n'
        code += '\t-- canBeAttacked = false,\n'
        code += '\t-- isUnique = true,   -- 持有是否唯一\n'
        code += '\t-- zeroDelete = true,\n'
        code += '\n'
        code += '\t-- cdTime = 8,\n'
        code += '\t-- canUseInCooling = true,\n'
        code += '}\n'
        code += '\n\n'
        code += '-- 拾取丢弃回调\n'
        code += '-- pack.onSwitch = function(holder, self, isAdd)\n'
        code += '\n'
        code += '-- end,\n'
        code += '\n'
        code += '\n'
        code += '-- pack.on_pickup = function(holder, item)\n'
        code += '--     local info = string.format(\n'
        code += '--         "[%s]拾取了物品：%s", holder:get_unit_name(), item:get_option("name"))\n'
        code += '--     printf.log(info)\n'
        code += '-- end,\n'
        code += '\n'
        code += '\n'
        code += '-- pack.on_drop = function(holder, item)\n'
        code += '--     local info = string.format(\n'
        code += '--         "[%s]丢弃了物品：%s", holder:get_unit_name(), item:get_option("name"))\n'
        code += '--     printf.log(info)\n'
        code += '-- end,\n'
        code += '\n'
        code += '\n'
        code += 'pack.on_use = function(holder, item)\n'
        code += '\tlocal p = holder:get_owner()\n'
        code += '\tlocal name = name\n'
        code += '\tX.battleSkill(p.id).use_item(name)\n'
        code += 'end\n'
        code += '\n'
        code += '\n'
        code += 'return ac.item:new(pack)\n'

        for v in lst:
            content = code.replace('itemName', v)
            path = f'E:\\workspace\\hoffen\\script\\game\\config\\item\\{module}\\{v}.lua'
            with open(path, 'w', encoding='utf-8') as obj:
                obj.write(content)

    def __get_buff_tpl_script(self):
        tpl_path = './python\\buff_template.lua'
        with open(tpl_path, 'r', encoding='utf-8') as obj:
            code = obj.read()
        return code

    def __get_mod_attr_script(self, desc):
        """获取mod_attr函数的lua代码

        Args:
            desc (str): 效果的描述信息

        Returns:
            str: mod_attr函数的lua代码
        """
        pattern = "([^,，nN]+)[+-]<([A-K])>(%?)"
        d = {}
        code = ''
        for v in re.finditer(pattern, desc):
            attr = v.groups()[0]
            data_index = v.groups()[1]
            suffix = v.groups()[2]
            # print(f'attr = {attr}, data_index = {data_index}')
            d[attr] = data_index
            code += f'u:change_attr("{attr}{suffix}", cfg.data{data_index} * rate)\n\t'

        code = code.rstrip('\n\t')
        return code

    def write_buff_tpl(self):
        """批量写Buff模版文件

        Args:
            module (str): 模块名称
            cfg_name (str): 配置表名称
        """
        module = self.__ws.title
        cfg_name = self.__ws.cell(1,1).value
        min_row, max_row = self.__get_rows()
        col_id = self.__get_col_id("name")
        desc_col_id = self.__get_col_id("fmt_desc")
        id_col_id = self.__get_col_id("id")
        name_lst = [c.value for c in list(self.__ws.columns)[col_id]][min_row-1:max_row]
        desc_lst = [c.value for c in list(self.__ws.columns)[desc_col_id]][min_row-1:max_row]
        id_lst = [c.value for c in list(self.__ws.columns)[id_col_id]][min_row-1:max_row]

        tpl = self.__get_buff_tpl_script()
        for i, name in enumerate(name_lst):
            # name = f'羁绊{name}'
            code = tpl
            code = code.replace('<name>', name)
            code = code.replace('<module>', module)
            code = code.replace('<cfg_name>', cfg_name)
            code = code.replace('<id>', str(id_lst[i]))

            # 写入mod_attr()
            desc = desc_lst[i]
            code = code.replace('-- <mod_attr>', self.__get_mod_attr_script(desc))

            path = f'{self.__ws.cell(4, 1).value}/{name}.lua' if self.__ws.cell(4, 1).value else None
            self.__write_file(code, path)
        print(f'总计{len(name_lst)}个文件已生成完毕')
